Copyright ã1995 by NeXT Computer, Inc.  All Rights Reserved.

NXSoundStream

Inherits From:	Object

Declared In:	soundkit/NXSoundStream.h

Class Description

NXSoundStream is an abstract superclass; each subclass represents a single stream of sound samples.  Currently, the Sound Kit provides two subclasses of NXSoundStream:

·	NXRecordStream represents sound recorded through the microphone jack.
·	NXPlayStream represents sound that's sent to sound output (the speaker, line-out jacks, and headphone jack).

The utility of NXSoundStream is invested in these subclasses; the NXSoundStream class itself simply defines methods that are common to them.  In addition, you can't create useful subclasses of NXSoundStream yourself.  

Many applications needn't bother with NXSoundStream and its subclasses; in general, the methods provided by the Sound class suffice for applications that record and playback sounds.  However, while Sound objects are easy to use, you can only record or play one sound at a time.  The primary advantage of using NXSoundStream objects is that they let you record and playback multiple simultaneous sounds.

Streams and Devices

To be of use, an NXSoundStream object must connect it to an instance of an NXSoundDevice subclass:  For recording you connect an NXRecordStream to an instance of NXSoundIn, and for playback you connect NXPlayStreams to NXSoundOuts.  The connection is formed as the NXSoundStream is initialized, through the initOnDevice: or initOnDevice:withParameters: method.  The latter method lets you provide further configuration of the NXSoundStream through the use of an NXSoundParameters object.  See the ªTypes and Constantsº section for a list of parameter keys that are meaningful to an NXSoundStream.

Any number of NXSoundStream objects can be connected to the same NXSoundDevice.  For recording, this creates multiple copies of the same dataÐone copy for each NXRecordStream.  These copies can even be spread across applications:  All NXRecordStreams that are actively listening to the NXSoundIn device will receive the data that's being recorded, regardless of the application that they're in.  Similarly, by connecting more than one NXPlayStream to an NXSoundOut object, you can mix several sounds during playback, possibly from different applications.   See the NXSoundIn and NXSoundOut classes for more on simultaneous recording and playback.

Using a Sound Stream

Having connected an NXSoundStream to an NXSoundDevice, you must tell the sound driver that you want the NXSoundStream to be involved in a recording or playback.  This is done through the activate method.  Activating an NXSoundStream uses valuable sound driver resources, thus it's best to activate the object just before you want to record or play a sound and deactivate it (through the deactivate method) soon after you've finished.

Activating an NXSoundStream doesn't cause it to instantly start recording or playing.  For this, you must enqueue sound buffers with the sound device:  For recording you enqueue empty buffers that are filled with data and delivered back to your application, for playback you enqueue buffers filled with the data that you want to play.  These tasks are performed through methods defined by the respective subclasses.  The thing to keep in mind is that you must deliver these buffers constantly and steadily while the stream is running.  This is the essential programming difference between using a Sound object and a NXSoundStream:  A Sound object can be ªturned onº and then ignored; an NXSoundStream demands constant attention.  You can ameliorate this by supplying the NXSoundStream with large buffers, although this affords less dynamic control over the data in the stream.

Important:  An NXSoundStream's sound data buffers aren't the same as an NXSoundDevice's DMA transfer buffers.  The former can be arbitrarily large; the latter is restricted to a page of virtual memory.

As an NXSoundStream delivers sound buffers to the sound driver, the sound driver sends back Mach messages to the NXSoundDevice class, messages that report on a device's status and, for recording, deliver freshly recorded data.  The NXSoundDevice class forwards this information to the delegate of the appropriate NXSoundStream.  The delegate methods defined by the NXSoundStream class mark general watershed moments in a stream's career:  when it starts, ends, pauses, and resumes.  NXRecordStream and NXPlayStream augment this collection with record- and playback-specific notification methods.

Sound Stream Errors

Most of NXSoundStream's methods communicate with the sound driver; many of these return NXSoundDeviceError error codes, which enumerate the situations that can thwart this communication.  The NXSoundDeviceError codes are listed in NXSoundDevice class specification.  NXSoundDevice's textForError: method translates these error codes into localized strings that you can display in your application.

Other methods, such as pause: and resume:, also communicate with the sound driver, but don't return NXSoundDeviceError codes.  However, such methods are susceptible to driver-communication errors and maintain a private variable to note their occurences.  You should follow these methods (which are listed in NXSoundDevice and noted in the descriptions below) with invocation of lastError, a method that returns the last NXSoundDeviceError code that was provoked.

Instance Variables

id delegate;

delegate	The receiver of notification messages.	

Method Types

Configuring an NXSoundStream
- init
- initOnDevice:
- initOnDevice:withParameters:
- setDevice:
- device
- parameters
- free

Activating and Deactivating	- activate
- deactivate

Controlling the stream	- abort:
- abortAtTime:
- pause:
- pauseAtTime:
- resume:
- resumeAtTime:

Querying the object	- bytesProcessed
- isActive
- isPaused
- streamPort
- lastError

Assigning a delegate	- setDelegate:
- delegate

Instance Methods

abort:

- abort:sender

Stops the NXSoundStream's playback or recording (after the current DMA transfer buffer has been processed), removes its remaining enqueued buffers, and sends the object's delegate a soundStreamDidAbort:deviceReserved: message.  The argument is ignoredÐit's included so the method can be used in Interface Builder as an action method.  You should follow this method with an invocation of lastError to see if an error occured.   If the NXSoundStream isn't currently active, this does nothing.  Returns self.

See also:  - abortAtTime:

abortAtTime:

- (NXSoundDeviceError)abortAtTime:(NXSoundStreamTime *)time

Schedules the NXSoundStream to be aborted (as described in the abort: method, above) at the time specified in the structure time.  The NXSoundStreamTime structure is a cover for the familiar timeval structure:

struct timeval {
     long tv_sec;   /* seconds */
     long tv_usec;  /* microseconds */
};

The value given by time is absolute; to abort a stream after a given number of seconds have elapsed, you need to know the present time.  This can be retrieved through system calls such as gettimeofday().  

This method returns immediatelyÐit doesn't wait for the stream to abort.  A soundStreamDidAbort:deviceReserved: message is sent to the NXSoundStream's delegate when the abortion is performed.

You should follow this method with an invocation of lastError to see if an error occured.  If the NXSoundStream isn't active when this method is invoked or when the specified time is met, this does nothing.   If the specified time is in the past, the object is aborted immediately.  Returns self.

See also:  - abort:

activate

- (NXSoundDeviceError)activate

Adds the NXSoundStream to the sound driver's list of active streams.  You must invoke this method before you enqueue buffers on the stream.  When you've finished recording or playing, you should send the NXSoundStream a deactivate: message.  The NXSoundStream must be connected to an NXSoundDevice for this method to have an effect.  An error code is returned.

See also:  - deactivate, - isActive

bytesProcessed

- (unsigned int)bytesProcessed

Returns the number of bytes of sound that the NXSoundStream has recorded or played since it was most recently activated.  Returns 0 if the object is inactive, or if an error occurs.  You should follow this method with an invocation of lastError to see if an error occured.

deactivate

- (NXSoundDeviceError)deactivate

Aborts the NXSoundStream's current activity and removes the object from the sound driver's list of active streams.

See also:  - activate, - isActive

delegate

- delegate

Returns the NXSoundStream's delegate.

See also:  - setDelegate:

device

- device

Returns the NXSoundDevice object that the NXSoundStream is connected to. 

See also:  - initOnDevice:, - setDevice:

free

- free

Deactivates and frees the NXSoundStream.

init

- init

Initializes the NXSoundStream without connecting it to an NXSoundDevice.  Returns self.

See also:  - initOnDevice:, - setDevice:

initOnDevice:

- initOnDevice:aDevice

Initializes the NXSoundStream and connects it to aDevice, which should be an instance of an NXSoundDevice subclass.  Returns self.

See also:  - init

initOnDevice:withParameters:

- initOnDevice:aDevice withParameters:(<NXSoundParameters>)params

Initializes the NXSoundStream, configures it by reading the appropriate parameters from  params, and connects it to aDevice, which should be an instance of an NXSoundDevice subclass.  Returns self.

See also:  - init

isActive

- (BOOL)isActive

Returns YES if the NXSoundStream is currently activate; otherwise, NO.

See also:  - activate

isPaused

- (BOOL)isPaused

Returns YES if the NXSoundStream is currently paused; otherwise, NO.

See also:  - pause:, - isActive

lastError

- (NXSoundDeviceError)lastError

Returns the most recent sound device error associated with the NXSoundSound.  Many methods don't explicitly return an NXSoundDeviceError, but set an internal variable, which can be retrieved with this method.  To retrieve localized text that describes the error, pass the value returned by this method to the textForError: NXSoundDevice class method.

See also:  + textForError: (NXSoundDevice)

parameters

- (<NXSoundParameters>)parameters

Returns the NXSoundParameters object that was used to configure the NXSoundStream.

pause:

- pause:sender

Pauses the NXSoundStream's recording or playback (after the current DMA transfer buffer has been processed) and sends a soundStreamDidPause: message to the object's delegate.  The argument is ignoredÐit's included so the method can be used in Interface Builder as an action method.  You should follow this method with an invocation of lastError to see if an error occured.   If the NXSoundStream isn't currently active or if it's already paused, this does nothing.  Returns self.

See also:  - pauseAtTime:, - resume:

pauseAtTime:

- (NXSoundDeviceError)pauseAtTime:(NXSoundStreamTime *)time

Schedules the NXSoundStream to be paused (as described in the pause: method, above) at the time specified in the structure time.  See the abortAtTime: method for an explanation of the NXSoundStreamTime type.  This method returns immediatelyÐit doesn't wait for the stream to pause.  A soundStreamDidPause: message is sent to the NXSoundStream's delegate at the time that the stream is paused.  This does nothing if the NXSoundStream isn't currently active.  An error code is returned.

See also:  - pause:, - abortAtTime:

resume:

- resume:sender

Resumes the NXSoundStream's recording or playback (after the current DMA transfer buffer has been processed) and sends a soundStreamDidResume: message to the object's delegate.  The argument is ignoredÐit's included so the method can be used in Interface Builder as an action method.  You should follow this method with an invocation of lastError to see if an error occured.  If the NXSoundStream isn't currently active or if it isn't paused, this does nothing.  Returns self.

See also:  - resumeAtTime:, - pause:

resumeAtTime:

- (NXSoundDeviceError)resumeAtTime:(NXSoundStreamTime *)time

Schedules the NXSoundStream to be resumed (as described in the resume: method, above) at the time specified in the structure time.  See the abortAtTime: method for an explanation of the NXSoundStreamTime type.  This method returns immediatelyÐit doesn't wait for the stream to resume.  A soundStreamDidResume: message is sent to the NXSoundStream's delegate at the time that the stream is resumed.  This does nothing if the NXSoundStream isn't currently active.  An error code is returned.

See also:  - pause:, - abortAtTime:

setDelegate:

- setDelegate:anObject

Assigns anObject as the NXSoundStream's delegate.

See also:  - delegate

setDevice:

- (NXSoundDeviceError)setDevice:aDevice

Connects the NXSoundStream to aDevice, which should be an instance of an NXSoundDevice subclass.  If the NXSoundStream is currently active, it immediately starts transferring sound to or from the new device.  An error code is returned.

See also:  - initOnDevice:, - device

streamPort

- (port_t)streamPort

Returns the port that the NXSoundStream uses to connect to the sound driver.  You can't set this port yourself, and you normally don't need to note its identity; this method is provided in case you want to pass the port as an argument to a function such as port_status().  (Note that this device port isn't understood by the old Sound/DSP driver, and thus shouldn't be used as an argument to the sound driver functions.) 

Methods Implemented By The Delegate

soundStream:didCompleteBuffer:

- soundStream:sender didCompleteBuffer:(int)tag

Invoked when the driver finishes playing or recording the sound buffer identified by tag (as assigned when the buffer was enqueued).  The return value is ignored.

See also:   - recordSize:tag: (NXRecordStream), - playBuffer:size:tag: (NXPlayStream)

soundStream:didStartBuffer:

- soundStream:sender didStartBuffer:(int)tag

Invoked when the driver starts playing or recording the sound buffer identified by tag (as assigned when the buffer was enqueued).    The return value is ignored.

See also:   - recordSize:tag: (NXRecordStream), - playBuffer:size:tag: (NXPlayStream)

soundStreamDidAbort:deviceReserved:

- soundStreamDidAbort:sender deviceReserved:(BOOL)flag

Invoked when the driver aborts the stream.  If the stream was aborted because the NXSoundDevice was reserved, flag will be YES, otherwise if will be NO.  The return value is ignored.

See also:  - abort:, - abortAtTime:, - setReserved: (NXSoundDevice)

soundStreamDidPause:

- soundStreamDidPause:sender

Invoked when the NXSoundStream sender is paused.  The return value is ignored.

See also:  - pause:, - pauseAtTime:

soundStreamDidResume:

- soundStreamDidResume:sender

Invoked when the NXSoundStream sender is resumed.  The return value is ignored.

See also:  - resume:, - resumeAtTime: